ffmpeg 从视频流中抓取图片

您所在的位置:网站首页 图片数字解码成代码 从电脑的角度看照片 ffmpeg 从视频流中抓取图片

ffmpeg 从视频流中抓取图片

2024-07-11 22:48| 来源: 网络整理| 查看: 265

从视频中不断抓取图片的基本流程:打开视频流地址->获取视频流packt->解码成图片帧->输出图片

一.初始化Ffmpeg

void ffmpegInit(){ av_register_all(); avformat_network_init(); av_log_set_level(AV_LOG_ERROR); }

  如果你不想输出log,设置log级别为AV_LOG_PANIC。

二.打开视频。

int Open(char* url) {    context = avformat_alloc_context();      context->interrupt_callback.opaque = this; //C++     context->interrupt_callback.callback = interruptCallback;//设置回调函数,否则有可能ffmpeg一直被挂住。      context->start_time_realtime = av_gettime();    AVDictionary* options = nullptr; av_dict_set(&options, "rtsp_transport", "udp", 0); //以udp方式打开,如果以tcp方式打开将udp替换为tcp av_dict_set(&options, "stimeout", "3000000", 0);  //设置超时断开连接时间  int ret = avformat_open_input(&context, url, nullptr, &options); //avformat_open_input 返回0表示open成功,小于0表示open失败   if(ret < 0) return ret;   ret = avformat_find_stream_info(context, options); ///avformat_find_stream_info 返回0表示查抄stream info成功 小于0表示失败。    if(options!= nullptr)    {       av_dict_free(options);    }   return ret;   } int interrupt_cb(void *ctx) { if((av_gettime() - ffmpeg->lastFrameRealtime) > 10 * 1000 * 1000) //10s超时退出 { return AVERROR_EOF; } return 0; }

三 .读取视频包:

shared_ptr ReadPacket() { shared_ptr packet((AVPacket*)av_malloc(sizeof(AVPacket)), [&](AVPacket *p){av_free_packet(p);av_freep(&p);}); av_init_packet(packet.get()); lastFrameRealtime = av_gettime(); int ret = av_read_frame(context, packet.get()); if(ret >= 0) { return packet; } else { return nullptr; } }

  说明一下:不一定要用智能指针。我确定这样写不会有内存泄露,所以就不改了,随手写的代码会有bug。

四. 解码

    1. 初始化解码器

InitDecoderCodec {   int ret = -1;   for(int i = 0;  i < context->nb_streams; ++i) { AVCodecContext *codecContext = context->streams[i]->codec; if(codecContext->codec_type == AVMEDIA_TYPE_VIDEO) {      //返回小于0,打开解码器失败 ret = avcodec_open2(codecContext, avcodec_find_decoder(codecContext->codec_id), &options); } } return ret; }

   2. 解码视频包

AVFrame* DecodeVideoPacket(AVCodecContext* codecContext){ AVFrame* videoFrame = av_frame_alloc(); auto hr = avcodec_decode_video2(codecContext, frame, &gotFrame, packet); if(hr >= 0 && gotFrame != 0) {    return videoFrame; }   else   {    avcodec_free_frame(&videoFrame);    return nullptr   }}

输出图片:

 uint8_t *GetPictureData(int width,int height, int *bufferSize){ pFrameYUV= av_frame_alloc(); uint8_t *out_buffer; out_buffer = new uint8_t[avpicture_get_size(PIX_FMT_RGB32, width, height)]; avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_RGB32, width, height); sws_scale(sws, (const uint8_t* const*)frame->data, frame->linesize, 0, height, pFrameYUV->data, pFrameYUV->linesize); *bufferSize = width * height * 4;  return pFrameYUV->data[0];}

 context是全局变量,如果有问题,加群流媒体/Ffmpeg/音视频 127903734或者766718184进行交流

视频下载地址:http://www.chungen90.com/?list_53

 Demo下载地址: http://www.chungen90.com/?list_52



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3